package com.ryan.plugin.store;

import java.util.*;

public class Store {
    private static Store instance;

    private final HashMap<AClass, HashMap<String, String>> data;
    private final HashMap<AClass, HashMap<String, String>> exceptions;
    private final HashMap<String, Boolean> packages;

    public static Store getInstance() {
        if (instance == null) instance = new Store();
        return instance;
    }

    private Store() {
        data = new HashMap<>();
        exceptions = new HashMap<>();
        packages = new LinkedHashMap<>();
    }

    public HashMap<AClass, HashMap<String, String>> getData() {
        return data;
    }

    public HashMap<AClass, HashMap<String, String>> getExceptions() {
        return exceptions;
    }

    public void reset() {
        data.clear();
        exceptions.clear();
    }

    /**
     * 存放类解析结果, 不包含函数
     * @param qualifiedSignature 包含完整的包名与类名
     */
    public void put(String qualifiedSignature) {
        String[] parts = qualifiedSignature.split("[.]");
        String className = parts[parts.length - 1];
        String packageName = qualifiedSignature.replace(("." + className), "");
        AClass aClass = new AClass(packageName, className);
        data.putIfAbsent(aClass, null);
    }

    /**
     * 存放类解析结果以及类的来源
     * @param qualifiedSignature 包含完整的包名与类名
     * @param classFrom 类的来源
     */
    public void put(String qualifiedSignature, String classFrom) {
        String[] parts = qualifiedSignature.split("[.]");
        String className = parts[parts.length - 1];
        String packageName = qualifiedSignature.replace(("." + className), "");
        AClass aClass = new AClass(packageName, className);
        aClass.from = classFrom;
        if (data.containsKey(aClass)) {
            HashMap<String, String> value = data.get(aClass);
            data.put(aClass, value);
        } else {
            data.put(aClass, null);
        }
    }

    /**
     * 存放函数解析结果
     * @param packageName 函数所在类的包名
     * @param className 函数所在类的类名
     * @param method 函数签名
     */
    public void put(String packageName, String className, String method) {
        put(packageName, className, method, "");
    }

    public void put(String packageName, String className, String method, String tag) {
        AClass aClass = new AClass(packageName, className);
        HashMap<String, String> methods = data.get(aClass);
        if (methods == null) {
            methods = new HashMap<>();
        }

        methods.put(method, tag);
        data.put(aClass, methods);
    }

    /**
     * 存放类解析结果以及类是否被继承或者实现
     * @param packageName 类的包名
     * @param className 类的包名
     * @param isImplements 是否被实现, true则被实现, false则被继承
     */
    public void putExtends(String packageName, String className, boolean isImplements) {
        AClass a = new AClass(packageName, className);
        data.forEach(((aClass, map) -> {
            if (aClass.equals(a)) aClass.tag = isImplements ? "implements" : "extends";
        }));
    }

    /**
     * 存放解析错误的结果
     * @param packageName 出现错误的源文件的包名
     * @param className 出现错误的源文件的类名
     * @param expr 出现错误的语句
     */
    public void putException(String packageName, String className, String expr) {
        AClass aClass = new AClass(packageName, className);
        HashMap<String, String> expressions = exceptions.get(aClass);
        if (expressions == null) {
            expressions = new HashMap<>();
        }

        expressions.put(expr, "");
        exceptions.put(aClass, expressions);
    }

    public void putPackage(String packageName) {
        packages.put(packageName, true);
    }

    public void checkIfFromSource() {
        data.forEach((aClass, map) -> {
            Boolean isInPackage = packages.get(aClass.packageName);
            if (isInPackage != null && isInPackage) {
                aClass.from = "source";
            }
        });
    }

    @Override
    public String toString() {
        return "Store{" +
                "data=" + data +
                ", exceptions=" + exceptions +
                '}';
    }
}
